<?php
/**
* Security tools
*
* Used to implement escaping functions, etc
*
* @package Temply-Account\Core
* @license GPL-2.0
* @author Sergey Dilong
*/
/**
* Security class
*
* Vars checking, token generating, encrypting
*
* @package Temply-Account\Core
* @license GPL-2.0
* @author Sergey Dilong
*
*/
class security
{
/**
* Var filter
*
* Make variables and arrays secure and clear
*
* @see self::clean() Cleaning function
*
* @param mixed $a Var to check
* @param bool $n Output check. If `true` - types won't be changed
* @return mixed Checked var
* @throws apiException
* * [103] Checking failed
*/
public static function filter($a, $n = false)
{
// If not array - var check
if (!is_array($a)) {
try {
$r = security::clean($a, $n);
// If failed - error
} catch (Exception $e) {
$w = ["warning" => "Contact Administration with Report ID, please"];
if (DEBUG_MODE) {
$w["error_info"] = __ExceptionToArray($e);
}
throw new apiException(103, $w);
}
// If array - copy
} else {
$r = $a;
}
// Check each key
foreach ($r as $k => $v) {
$r[$k] = security::filter($v);
if (is_string($r[$k]) && preg_match('/^([\s]+)?$/', $r[$k])) {
unset($r[$k]);
}
}
return $r;
}
/**
* Var clean
*
* Make variables clear and correct
*
* @param mixed $a Var to check
* @param bool $n Output check. If `true` - types won't be changed
*
* @return mixed Result
*/
public static function clean($a, $n = false)
{
// If not output mode
if (!$n) {
if ($a === "true" || $a === "false") {
$a = boolval($a);
}
//BOOLify
else if (is_numeric($a) && intval($a) == floatval($a)) {
$a = intval($a);
}
//INTify
else if (is_numeric($a)) {
$a = floatval($a);
}
//FLOATify
} else if (is_string($a)) { //STRINGify
$a = trim($a);
// Replace multi-spaces
$a = preg_replace("/ +/", " ", $a);
$a = htmlspecialchars($a, ENT_DISALLOWED, 'UTF-8');
}
return $a;
}
/**
* Get Token
*
* Generates crypt-secure random string for token (HEX)
*
* @param int $l Token length
* @return string Token
*/
public static function token_str($l = 64)
{
return bin2hex(random_bytes($l));
}
/**
* Encrypt
*
* Encrypts text
*
* @param string $plaintext Text to encrypt
* @param array $o Options
* * *key* - salt
* *cipher* - encryption method. Default = `aes-128-gcm`
*
* @return string[]|bool Returns `[$encrypted, $iv, $tag, $key ]` or `false` if failed
*/
public static function encrypt($plaintext, $o = [])
{
// Automatic generation
if (!count($o)) {
$o = ["key" => self::token_str(5), "cipher" => "aes-128-gcm"];
}
// Stringify
$plaintext = strval($plaintext);
// If all set
if (in_array($o['cipher'], openssl_get_cipher_methods())) {
// Encrypt
$ivlen = openssl_cipher_iv_length($o['cipher']);
$iv = openssl_random_pseudo_bytes($ivlen);
$ciphertext = openssl_encrypt($plaintext, $o['cipher'], $o["key"], $options = 0, $iv, $tag);
// Check
$original_plaintext = self::decrypt($ciphertext, $o["key"], $iv, $tag);
if ($plaintext !== $original_plaintext) {
return false;
}
// Return data
return [$ciphertext, $iv, $tag, $key];
} else {
return false;
}
}
/**
* Decrypt
*
* Decrypts string
*
* @param string $ciphertext Encodedtext
* @param string $key Key
* @param string $iv IV
* @param string $tag Tag
* @param array $o Options
* * *cipher* - Encryption method. Default = `aes-128-gcm`
* @return string|bool Result. If `false` - failed.
*/
public static function decrypt($ciphertext, $key, $iv, $tag, $o = [])
{
// Set encoding
if (!count($o)) {
$o = ["cipher" => "aes-128-gcm"];
}
// Decode
if (in_array($o['cipher'], openssl_get_cipher_methods())) {
return openssl_decrypt($ciphertext, $o["cipher"], $key, $options = 0, $iv, $tag);
} else {
return false;
}
}
}